﻿using System;
using System.IO;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Navigation;
using System.Collections.Generic;
using System.Linq;
using System.Xml.Linq;
using System.Windows.Input;
using System.Runtime.InteropServices;

namespace PWS
{
	public partial class MainWindow
	{
        List<PasswordEntry> Passwords=new List<PasswordEntry>();
        String SearchText;
        byte[] Password=null;

        public MainWindow()
		{
			this.InitializeComponent();
			
			// Insert code required on object creation below this point.
            SearchText = SearchTextBox.Text;
            Password = new byte[0];
        }

        private void LayoutRoot_MouseDown(object sender, System.Windows.Input.MouseButtonEventArgs e)
        {
            if (e.ChangedButton == System.Windows.Input.MouseButton.Left)
                this.DragMove();
        }

        private void Window_Loaded(object sender, RoutedEventArgs e)
        {
            LoadPasswords();

            UpdatePasswordView();
		}

        private string GetDataFilePath()
        {
            return Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData)+@"\PasswordStorage";
        }
        
        static byte[] entropy = { 160, 221, 154, 76, 46, 123, 248, 11, 6, 82 };
        private byte[] EncryptData(byte[] data,byte[] password)
        {
            return System.Security.Cryptography.ProtectedData.Protect(data, password!=null?password:entropy , System.Security.Cryptography.DataProtectionScope.CurrentUser);
        }

        private byte[] DecryptData(byte[] data,byte[] password)
        {
            return System.Security.Cryptography.ProtectedData.Unprotect(data, password!=null?password:entropy, System.Security.Cryptography.DataProtectionScope.CurrentUser);
        }

        private void SavePasswords()
        {
            if (Password.Length <= 0)
            {
                LogIn pw = new LogIn();
                if (pw.ShowDialog().GetValueOrDefault(false))
                    Password = pw.GetPassword();                
            }

            XElement xml = new XElement("PasswordStorage", from p in Passwords select 
                                                               new XElement("Password", new XAttribute("Title", p.TITLE), new XAttribute("Username", p.USERNAME), new XAttribute("Password", p.PASSWORD), new XAttribute("Notes", p.NOTES)));

            byte[] data = System.Text.Encoding.Unicode.GetBytes(xml.ToString(SaveOptions.DisableFormatting));
            data = EncryptData(data, Password);
            System.IO.Directory.CreateDirectory(GetDataFilePath());
            System.IO.File.WriteAllBytes(GetDataFilePath()+@"\PasswordStorage.dat", data);
        }

        private void LoadPasswords()
        {
            if (File.Exists(GetDataFilePath()+@"\PasswordStorage.dat"))
            {
                byte[] data = System.IO.File.ReadAllBytes(GetDataFilePath()+@"\PasswordStorage.dat");

                bool loaded = false;
                do
                {
                    LogIn pw = new LogIn();
                    if (!pw.ShowDialog().GetValueOrDefault(false))
                    {
                        Close();
                        return;
                    }
                    Password = pw.GetPassword();                   
                    
                    try
                    {
                        data = DecryptData(data, Password);
                        loaded = true;
                    }
                    catch (System.Security.Cryptography.CryptographicException)
                    {
                        MessageBox.Show(
                            "The master password provided is incorrect.",
                            "Incorrect Password",
                            MessageBoxButton.OK,
                            MessageBoxImage.Warning);
                    }
                } while (!loaded);


                XDocument doc = XDocument.Parse(System.Text.Encoding.Unicode.GetString(data));

                IEnumerable<PasswordEntry> results = from elem in doc.Descendants("Password")
                                                     select new PasswordEntry
                                                         {
                                                             TITLE = elem.Attribute("Title").Value,
                                                             USERNAME = elem.Attribute("Username").Value,
                                                             PASSWORD = elem.Attribute("Password").Value,
                                                             NOTES = elem.Attribute("Notes").Value,
                                                         };

                Passwords.AddRange(results);
            }                       
        }

        private void UpdatePasswordView()
        {
            if (PasswordsListBox != null)
            {
                object selectedItem = PasswordsListBox.SelectedItem;

                if (SearchTextBox.Text.Length>0 && SearchTextBox.Text != SearchText)
                {
                    var entries = from entry in Passwords where entry.TITLE.IndexOf(SearchTextBox.Text, StringComparison.InvariantCultureIgnoreCase) >= 0 || entry.USERNAME.IndexOf(SearchTextBox.Text, StringComparison.InvariantCultureIgnoreCase) >= 0 || entry.NOTES.IndexOf(SearchTextBox.Text, StringComparison.InvariantCultureIgnoreCase) >= 0 orderby entry.TITLE select entry;
                    PasswordsListBox.ItemsSource = entries;
                }
                else
                {
                    var entries = from entry in Passwords orderby entry.TITLE select entry;
                    PasswordsListBox.ItemsSource = entries;
                }

                PasswordsListBox.SelectedItem = selectedItem;
            }
        }


        void ExecuteAddItem(object sender, ExecutedRoutedEventArgs e)
        {
            EditWindow AddWindow = new EditWindow();
            if (AddWindow.ShowDialog().GetValueOrDefault(false))
            {
                PasswordEntry newEntry = new PasswordEntry();
                newEntry.TITLE = AddWindow.TitleTextBox.Text;
                newEntry.USERNAME = AddWindow.UsernameTextBox.Text;
                newEntry.NOTES = AddWindow.NotesTextBox.Text;
                newEntry.PASSWORD = AddWindow.PasswordTextBox.Text;
                Passwords.Add(newEntry);

                UpdatePasswordView();

                PasswordsListBox.SelectedItem = newEntry;

                SavePasswords();
            }
        }

        void ExecuteEditItem(object sender, ExecutedRoutedEventArgs e)
        {
            if (PasswordsListBox.SelectedItem != null)
                EditItem(PasswordsListBox.SelectedItem as PasswordEntry);
            else
                MessageBox.Show("Please select an item to edit", "Error");
        }

        void ExecuteDeleteItem(object sender, ExecutedRoutedEventArgs e)
        {
            if (PasswordsListBox.SelectedItem != null)
            {
                if (MessageBox.Show("Delete selected items?", "Confirm", MessageBoxButton.YesNo) == MessageBoxResult.Yes)
                {
                    foreach (object entry in PasswordsListBox.SelectedItems)
                    {
                        Passwords.Remove(entry as PasswordEntry);
                    }

                    UpdatePasswordView();

                    SavePasswords();
                }
            }
            else
                MessageBox.Show("Please select an item to delete", "Error");
        }

        void ExecuteHelp(object sender, ExecutedRoutedEventArgs e)
        {
            if(System.Threading.Thread.CurrentThread.CurrentUICulture.Name.Equals("ja-JP"))
                System.Windows.Forms.Help.ShowHelp(null, @"ja-JP\PasswordStorage.chm");
            else
                System.Windows.Forms.Help.ShowHelp(null, @"en-US\PasswordStorage.chm");
        }

        private void CloseButton_Click(object sender, RoutedEventArgs e)
        {
            Close();
        }

        private void TextBox_TextChanged(object sender, TextChangedEventArgs e)
        {
            UpdatePasswordView();
        }

        private void EditItem(PasswordEntry entry)
        {
            EditWindow EditWindow = new EditWindow();
            EditWindow.TitleTextBox.Text = entry.TITLE;
            EditWindow.UsernameTextBox.Text = entry.USERNAME;
            EditWindow.NotesTextBox.Text = entry.NOTES;
            EditWindow.PasswordTextBox.Text = entry.PASSWORD; 
            
            if (EditWindow.ShowDialog().GetValueOrDefault(false))
            {
                bool changed = false;
                if (entry.TITLE!=EditWindow.TitleTextBox.Text)
                {
                    changed = true;
                    entry.TITLE = EditWindow.TitleTextBox.Text;
                }

                if (entry.USERNAME != EditWindow.UsernameTextBox.Text)
                {
                    changed = true;
                    entry.USERNAME = EditWindow.UsernameTextBox.Text;
                }

                if (entry.NOTES != EditWindow.NotesTextBox.Text)
                {
                    changed = true;
                    entry.NOTES = EditWindow.NotesTextBox.Text;
                }

                if (entry.PASSWORD != EditWindow.PasswordTextBox.Text)
                {
                    changed = true;
                    entry.PASSWORD = EditWindow.PasswordTextBox.Text;
                }

                if (changed)
                {
                    UpdatePasswordView();

                    SavePasswords();
                }
            }
        }

        private void ClearButton_Click(object sender, RoutedEventArgs e)
        {
            SearchTextBox.Text = SearchText;
        }

        private void PasswordsListBox_MouseDoubleClick(object sender, System.Windows.Input.MouseButtonEventArgs e)
        {
            if(PasswordsListBox.SelectedItem!=null)
                EditItem(PasswordsListBox.SelectedItem as PasswordEntry);
        }

        private void SearchTextBox_GotKeyboardFocus(object sender, System.Windows.Input.KeyboardFocusChangedEventArgs e)
        {
            SearchTextBox.SelectAll();
        }

        private void SearchTextBox_GotMouseCapture(object sender, System.Windows.Input.MouseEventArgs e)
        {
            SearchTextBox.SelectAll();
        }

        private void Button_Click(object sender, RoutedEventArgs e)
        {
            System.Diagnostics.Process.Start("mailto:feedback@jwsecure.com");
        }
          
	}
}